"""
批量裁剪模块：处理批量视频裁剪相关的功能
包括批量上传、裁剪、进度查询、文件管理等
"""

import os
import time
import json
import asyncio
import shutil
import uuid
from pathlib import Path
from fastapi import HTTPException
from fastapi.responses import JSONResponse, FileResponse
from bbdown.core.logger import Logger

from .constants import UPLOAD_DIR, CUT_DIR, BATCH_CUT_TASKS
from .db import insert_result, update_task_status

logger = Logger()

async def batch_upload_video(video: bytes, filename: str) -> dict:
    """
    上传视频文件用于批量裁剪
    
    参数：
        video (bytes): 视频文件内容
        filename (str): 视频文件名
        
    返回：
        dict: 包含视频ID和文件名的字典
    """
    try:
        # 生成唯一文件名
        video_id = str(uuid.uuid4())
        file_path = UPLOAD_DIR / f"{video_id}_{filename}"
        
        # 保存文件
        with open(file_path, "wb") as f:
            f.write(video)
        
        return {
            "video_id": video_id,
            "filename": filename
        }
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"上传失败: {str(e)}")

async def batch_cut_video(
    video_id: str,
    tasks: str,
    user_id: str = None
) -> dict:
    """
    处理批量裁剪请求
    
    参数：
        video_id (str): 视频ID
        tasks (str): JSON格式的任务列表
        user_id (str): 用户ID
        
    返回：
        dict: 包含任务ID和状态的字典
    """
    task_id = str(uuid.uuid4())
    try:
        # 解析任务列表
        cut_tasks = json.loads(tasks)
        if not isinstance(cut_tasks, list):
            raise ValueError("任务格式错误")
            
        # 检查视频文件是否存在
        video_files = list(UPLOAD_DIR.glob(f"{video_id}_*"))
        if not video_files:
            raise ValueError("视频文件不存在")
            
        input_path = str(video_files[0])
        
        # 初始化任务状态
        BATCH_CUT_TASKS[task_id] = {
            "status": "running",
            "progress": 0,
            "current_step": "正在处理...",
            "input_path": input_path,
            "tasks": cut_tasks,
            "results": [],
            "created_at": time.time()
        }
        
        # 更新数据库中的任务状态
        update_task_status(task_id, "running")
        
        # 启动处理任务
        asyncio.create_task(
            process_batch_cut_tasks(
                task_id,
                input_path,
                cut_tasks
            )
        )
        
        return {"task_id": task_id}
    except Exception as e:
        # 更新数据库中的任务状态
        update_task_status(task_id, "error", {"error": str(e)})
        return {"error": str(e), "task_id": task_id}

async def process_batch_cut_tasks(task_id: str, input_path: str, tasks: list):
    """
    处理批量裁剪任务
    
    参数：
        task_id (str): 任务ID
        input_path (str): 输入文件路径
        tasks (list): 裁剪任务列表
    """
    try:
        results = []
        total_tasks = len(tasks)
        
        for i, task in enumerate(tasks):
            try:
                start_time = task["startTime"]
                end_time = task["endTime"]
                output_filename = task["fileName"]
                
                # 设置输出路径
                output_path = CUT_DIR / f"{task_id}_{output_filename}"
                
                # 使用ffmpeg进行裁剪
                cmd = [
                    'ffmpeg',
                    '-i', input_path,
                    '-ss', start_time,
                    '-to', end_time,
                    '-c:v', 'libx264',
                    '-preset', 'medium',
                    '-crf', '23',
                    '-c:a', 'aac',
                    '-b:a', '128k',
                    str(output_path)
                ]
                
                process = await asyncio.create_subprocess_exec(
                    *cmd,
                    stdout=asyncio.subprocess.PIPE,
                    stderr=asyncio.subprocess.PIPE
                )
                
                stdout, stderr = await process.communicate()
                
                if process.returncode == 0:
                    file_size = os.path.getsize(output_path)
                    results.append({
                        "name": output_filename,
                        "size": file_size,
                        "path": str(output_path)
                    })
                    # 插入结果表
                    insert_result(
                        task_id,
                        output_filename,
                        str(output_path),
                        file_size,
                        "video/mp4"
                    )
                else:
                    raise Exception(f"裁剪失败: {stderr.decode()}")
                
                # 更新进度
                progress = int((i + 1) / total_tasks * 100)
                BATCH_CUT_TASKS[task_id].update({
                    "progress": progress,
                    "current_step": f"正在处理第 {i + 1}/{total_tasks} 个片段"
                })
                
            except Exception as e:
                results.append({
                    "name": task["fileName"],
                    "error": str(e)
                })
        
        # 更新任务状态
        BATCH_CUT_TASKS[task_id].update({
            "status": "finished",
            "progress": 100,
            "current_step": "处理完成",
            "results": results
        })
        
        # 更新数据库中的任务状态
        update_task_status(task_id, "finished", {
            "results": results
        })
        
    except Exception as e:
        BATCH_CUT_TASKS[task_id].update({
            "status": "error",
            "error": str(e)
        })
        
        # 更新数据库中的任务状态
        update_task_status(task_id, "error", {"error": str(e)})

def get_batch_cut_status(task_id: str) -> dict:
    """
    获取批量裁剪任务状态
    
    参数：
        task_id (str): 任务ID
        
    返回：
        dict: 任务状态信息
    """
    if task_id not in BATCH_CUT_TASKS:
        raise HTTPException(status_code=404, detail="任务不存在")
    return BATCH_CUT_TASKS[task_id]

def get_batch_cut_file(task_id: str, filename: str) -> FileResponse:
    """
    获取单个裁剪后的视频文件
    
    参数：
        task_id (str): 任务ID
        filename (str): 文件名
        
    返回：
        FileResponse: 文件响应
    """
    if task_id not in BATCH_CUT_TASKS:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    task = BATCH_CUT_TASKS[task_id]
    if task["status"] != "finished":
        raise HTTPException(status_code=400, detail="视频尚未处理完成")
    
    # 查找对应的文件信息
    file_info = next((f for f in task["results"] if f["name"] == filename), None)
    if not file_info or "error" in file_info:
        raise HTTPException(status_code=404, detail="文件不存在")
    
    file_path = file_info["path"]
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="文件不存在")
    
    return FileResponse(
        file_path,
        filename=filename,
        media_type="video/mp4"
    )

async def batch_download_files(files: str) -> FileResponse:
    """
    批量下载多个任务的视频文件
    
    参数：
        files (str): JSON格式的文件列表
        
    返回：
        FileResponse: ZIP文件响应
    """
    try:
        # 解析要下载的文件列表
        file_list = json.loads(files)
        if not isinstance(file_list, list):
            raise ValueError("文件列表格式错误")
        
        # 创建临时目录
        temp_dir = CUT_DIR / f"batch_download_{int(time.time())}"
        temp_dir.mkdir(exist_ok=True)
        
        # 复制选中的文件到临时目录
        copied_files = []
        for file_info in file_list:
            task_id = file_info["task_id"]
            filename = file_info["name"]
            
            if task_id not in BATCH_CUT_TASKS:
                continue
                
            task = BATCH_CUT_TASKS[task_id]
            if task["status"] != "finished":
                continue
            
            # 查找对应的文件信息
            file_info = next((f for f in task["results"] if f["name"] == filename), None)
            if file_info and "error" not in file_info:
                try:
                    shutil.copy2(file_info["path"], temp_dir / filename)
                    copied_files.append(filename)
                except Exception as e:
                    logger.error(f"复制文件失败 {filename}: {str(e)}")
        
        if not copied_files:
            raise ValueError("没有找到任何可下载的文件")
        
        # 创建zip文件
        zip_path = CUT_DIR / f"batch_files_{int(time.time())}.zip"
        shutil.make_archive(str(zip_path).replace('.zip', ''), 'zip', temp_dir)
        
        # 清理临时目录
        shutil.rmtree(temp_dir)
        
        return FileResponse(
            str(zip_path),
            filename="cut_videos.zip",
            media_type="application/zip"
        )
        
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e)) 